package com.note.feng.juc.mutithread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author yuhf
 */
public class MutithreadDemo {

    /**
     * 面试题：
     * 一个线程池的核心线程数为10个，最大线程数为20个，阻塞队列的容量为30。现在提交45个
     * 任务，每个任务的耗时为500毫秒。
     * 请问：这批任务执行完成总计需要多少时间？注：忽略线程创建、调度的耗时。
     *
     * 答案：1500毫秒
     *
     * 解析：
     * 1.前10个认为，分别由10个核心线程处理；
     * 随后的30个认为，进入阻塞队列；
     * 剩余的5个认为，开启新线程执行；
     * 至此，45个任务，15个线程在执行15个任务，用时500毫秒。
     * 2.任务执行完，再取阻塞队列中的任务，继续执行，
     * 取15个任务，执行，用时500毫秒。
     * 3.再次取15个任务，执行，用时500毫秒。
     * 45个任务全部执行完成，用时 500 * 3 = 1500 毫秒
     *
     */
    public static void main(String[] args) {
        ThreadPoolExecutor executor =
                new ThreadPoolExecutor(10, 20,
                        60000L, TimeUnit.SECONDS,
                        new LinkedBlockingDeque<>(30));
        long start = System.currentTimeMillis();
        List<Future<Integer>> list = new ArrayList<>(45);
        for (int i = 0; i < 45; i++) {
            final int taskIndex = i;
            Future<Integer> future = executor.submit(() -> {
                System.out.println("start: " + taskIndex);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("end: " + taskIndex);
                System.out.println("当前活动线程的数量:" + executor.getActiveCount());
                System.out.println("已完成的任务数量:" + executor.getCompletedTaskCount());
                System.out.println("总任务数:" + executor.getTaskCount());
                System.out.println("当前线程池中的线程数量:" + executor.getPoolSize());
                System.out.println("线程池在任意时间点的最大线程数:" + executor.getLargestPoolSize());
                return taskIndex;
            });
            list.add(future);

        }
        list.forEach(f -> {
            try {
                f.get();
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException(e);
            }
        });
        System.out.println(System.currentTimeMillis() - start);
        executor.shutdown();
    }
}
